/**
 * 
 * 
 */
package at.fhhagenberg.mcm09.elevator.control;

import java.rmi.RemoteException;
import java.util.Observable;
import java.util.Observer;
import java.util.Queue;

import sqelevator.IElevator;
import at.fhhagenberg.mcm09.elevator.model.RequestModel;
import at.fhhagenberg.mcm09.elevator.model.StopRequest;



/**
 * @author Paul Latzelsperger This class is the main control instance to handle
 *         commands coming from the UI and also receives and forwards status
 *         update events coming from the elevator. In case automatic mode is
 *         selected, only status messages are forwared to ui, whereas in manual
 *         mode the control also takes action to respond to the requests.
 */
public class ElevatorControl /*extends Observable*/ implements Observer {

	/**
	 * specifies either the auto, or manual mode of the elevator control unit
	 */
	public enum ControlMode {
		AUTOMATIC, MANUAL
	}

	private ControlMode m_mode;
	private ElevatorAdapter m_adapter;
	private EventGenerator m_generator;
	private IAlgorithm m_algorithm;
	private int 		m_targetFloor;
	private boolean		m_manual;
	
	public ElevatorControl(IElevator _elevator, ElevatorAdapter _adtp, EventGenerator _gen) {
		m_mode = ControlMode.AUTOMATIC;
		m_manual = false;
		m_adapter = _adtp;
		m_algorithm=new ResortAlgorithm();
		m_generator = _gen;
		m_generator.addObserver(this);
	}

	@Override
	/**
	 * Method that is invoked by Observables, i.e. EventGenerators whenever an elevator status
	 * has changed.
	 */
	public void update(Observable _eventSrc, Object arg) {

		if(arg instanceof RequestModel){
			handleRequest((RequestModel)arg);
		}
		else{
			System.out.println("Info event received!");
		}

	}

	/**
	 * Method that is invoked whenever a request event is fired by the event
	 * generator. depending on whether the control is in auto or manual mode,
	 * events are either reacted to or discarded. Note, that no further
	 * forwarding is done here since any calling method must take care of this!
	 * 
	 * @param _evt
	 * @throws InterruptedException 
	 */
	public void handleRequest(RequestModel _rq) {

		switch (m_mode) {
			case AUTOMATIC:
				try {
					Queue<StopRequest> q = _rq.getStopQueue();
					int curFloor = m_adapter.getPosition();
					int targetFloor = m_algorithm.getTargetFloor(q,curFloor);
					
					
					if(targetFloor != m_targetFloor || m_manual){
						System.out.println("Target: " + targetFloor);
						Thread.sleep(2000);
						m_adapter.gotoFloor(targetFloor);
						m_targetFloor = targetFloor;
						m_manual = false;
						
					}
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				
				break;
				
			case MANUAL:
				m_manual = true;
				break;
		
		}// switch

	}
	
	public int getTargetFloor(){
		
		return m_targetFloor;
	}
	
	public void setControlMode(ControlMode _mode){
		m_mode = _mode;
//		StatusPlaintextEvent evt = new StatusPlaintextEvent("Info: Status changed to "+m_mode.toString()+"!");
//		setChanged();
//		notifyObservers(evt);
	}

	public ControlMode getControlMode(){
		return m_mode;
	}
	public void setCommand(StopRequest stopRequest) {
		try {
			
			m_adapter.gotoFloor(stopRequest.getTargetFloor());
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}

	public int getNextFloor() {
		try {
			return m_adapter.getTargetFloor();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
		
	}

}
